package org.abettor.util.mail;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.MimeMessage;

import org.apache.log4j.Logger;

/**
 * 发送电子邮件的类
 * @author <a href="http://www.abettor.org/" target="_blank">abettor</a>
 */
public class MailSender extends Thread
{
	private Address from;
	private List<Address> to = new ArrayList<Address>();
	private String title;
	private String content;
	private String serverAddr;
	private int serverPort = 25;
	private String helo;
	private boolean encrypt;
	private boolean auth;
	private String user;
	private String password;
	private String charset = "UTF-8";
	private String textMime = "plain";
	private final Logger logger = Logger.getLogger(this.getClass());
	private Set<MailListener> mailListeners = Collections.synchronizedSet(new HashSet<MailListener>());

	//TODO	本方法的执行结果应该通知mailListeners中的监听器
	/**
	 * @see java.lang.Thread#run()
	 */
	public void run()
	{
		//	设置邮件参数
		Properties p = new Properties();
		if(! encrypt)
		{
			p.put("mail.transport.protocol", "smtp");
			p.put("mail.smtp.host", serverAddr);
			p.put("mail.smtp.port", serverPort + "");
			p.put("mail.smtp.localhost", helo);
			p.put("mail.smtp.auth", "false");
			if(auth)
			{
				p.put("mail.smtp.auth", "true");
				p.put("mail.smtp.user", user);
				p.put("mail.smtp.password", password);
			}
		}
		else
		{
			p.put("mail.transport.protocol", "smtps");
			p.put("mail.smtps.host", serverAddr);
			p.put("mail.smtps.port", serverPort + "");
			p.put("mail.smtps.localhost", helo);
			p.put("mail.smtps.auth", "false");
			if(auth)
			{
				p.put("mail.smtps.auth", "true");
				p.put("mail.smtps.user", user);
				p.put("mail.smtps.password", password);
			}
		}

		//	获取会话
		Session ssn = null;
		if(auth)
		{
			ssn = Session.getDefaultInstance(p, new Authenticator()
			{
				protected PasswordAuthentication getPasswordAuthentication()
				{
					return new PasswordAuthentication(user, password);
				}
			});
		}
		else
		{
			ssn = Session.getDefaultInstance(p);
		}

		if(ssn == null)
		{
			return;
		}

		//	设置连接协议
		if(! encrypt)
		{
			ssn.setProtocolForAddress("rfc822", "smtp");
		}
		else
		{
			ssn.setProtocolForAddress("rfc822", "smtps");
		}

		//	设置邮件内容
		MimeMessage msg = new MimeMessage(ssn);
		try
		{
			msg.setFrom(from);
			msg.setSender(from);
			msg.setSentDate(new Date());
			msg.setSubject(title, charset);
			msg.setText(content, charset, textMime);
			int len = to.size();
			Address [] dest = new Address[len];
			Iterator<Address> it = to.iterator();
			int i = 0;
			while(it.hasNext())
			{
				Address addr = (Address) it.next();
				dest[i] = addr;
				i ++;
			}
			msg.setRecipients(Message.RecipientType.TO, dest);
		}
		catch(MessagingException e)
		{
			logger.debug("", e);
			return;
		}

		//	发送邮件
		try
		{
			Transport.send(msg);
		}
		catch (MessagingException e)
		{
			logger.debug("", e);
			return;
		}
	}

	/**
	 * 发送邮件
	 *
	 */
	public void send()
	{
		start();
	}

	/**
	 * 添加接收者
	 * @param to 接收者邮件地址
	 */
	public void addTo(Address to)
	{
		this.to.add(to);
	}

	/**
	 * 清除所有接收者
	 *
	 */
	public void clearTo()
	{
		this.to.clear();
	}

	/**
	 * 清除一位接收者
	 * @param to 要清除的接收者邮件地址
	 */
	public void removeTo(Address to)
	{
		this.to.remove(to);
	}

	/**
	 * 设置是否需要身份验证
	 * <br />默认为不需要
	 */
	public void setAuth(boolean auth)
	{
		this.auth = auth;
	}

	/**
	 * 设置要发送的邮件正文信息
	 * @param content 邮件正文
	 */
	public void setContent(String content)
	{
		this.content = content;
	}

	/**
	 * 设置是否需要安全的网络连接
	 * <br />默认为不需要
	 */
	public void setEncrypt(boolean encrypt)
	{
		this.encrypt = encrypt;
	}

	/**
	 * 设置HELO指令的地址，由于垃圾邮件验证
	 * @param helo 服务器域名或主机名
	 */
	public void setHelo(String helo)
	{
		this.helo = helo;
	}

	/**
	 * 设置身份验证密码
	 * <br />auth为false时不需要
	 * @param password 登录密码，明文
	 */
	public void setPassword(String password)
	{
		this.password = password;
	}

	/**
	 * 设置邮件服务器地址
	 * @param serverAddr 邮件服务器地址
	 */
	public void setServerAddr(String serverAddr)
	{
		this.serverAddr = serverAddr;
	}

	/**
	 * 设置邮件服务器所使用的端口
	 * <br />默认为25
	 * @param serverPort 邮件服务器所使用的端口
	 */
	public void setServerPort(int serverPort)
	{
		this.serverPort = serverPort;
	}

	/**
	 * 设置邮件标题
	 * @param title 邮件标题
	 */
	public void setTitle(String title)
	{
		this.title = title;
	}

	/**
	 * 设置身份验证的用户名
	 * <br />auth为false时不需要
	 * @param user 登录用户名
	 */
	public void setUser(String user)
	{
		this.user = user;
	}

	/**
	 * 设置发件人电子邮件地址
	 * @param from 发件人地址
	 */
	public void setFrom(Address from)
	{
		this.from = from;
	}

	/**
	 * 设置发送邮件所使用的字符编码
	 * <br />默认为UTF-8
	 * @param charset 字符编码名称
	 */
	public void setCharset(String charset)
	{
		this.charset = charset;
	}

	/**
	 * 设置发送邮件正文的子类型
	 * <br />默认为plain，可选的有plain、html、xml等
	 * @param textMime 邮件文本正文子类型
	 */
	public void setTextMime(String textMime)
	{
		this.textMime = textMime;
	}

	/**
	 * 添加邮件处理结果事件监听器
	 */
	public void addMailListener(MailListener mailListener)
	{
		mailListeners.add(mailListener);
	}

	/**
	 * 删除邮件处理结果事件监听器
	 */
	public void removeMailListener(MailListener mailListener)
	{
		mailListeners.remove(mailListener);
	}

	/**
	 * 删除所有邮件处理结果事件监听器
	 */
	public void removeAllMailListener()
	{
		mailListeners.clear();
	}
}
